{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "---\n",
    "title: Variables\n",
    "sidebar_position: 3\n",
    "description: Introduction to Mojo variables.\n",
    "---"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A variable is a name that holds a value or object. All variables in Mojo are \n",
    "mutable—their value can be changed. (If you want to define a constant value that\n",
    "can't change at runtime, see the \n",
    "[`alias` keyword](/mojo/manual/parameters/#alias-named-parameter-expressions).)\n",
    "\n",
    "Mojo has two kinds of variables:\n",
    "\n",
    "- Explicitly-declared variables are created with the `var` keyword, and may include\n",
    "  [type annotations](#type-annotations).\n",
    "\n",
    "  ```mojo\n",
    "  var a = 5\n",
    "  var b: Float64 = 3.14\n",
    "  ```\n",
    "  \n",
    "- Implicitly-declared variables are created with an assignment statement:\n",
    "\n",
    "  ```mojo\n",
    "  a = 5\n",
    "  b = 3.14\n",
    "  ```\n",
    "\n",
    "Both types of variables are strongly-typed: the variable receives a type when\n",
    "it's created, and the type never changes. You can't assign a variable a value of\n",
    "a different type:\n",
    "\n",
    "```mojo\n",
    "count = 8 # count is type Int\n",
    "count = \"Nine?\" # Error: can't implicitly convert 'StringLiteral' to 'Int'\n",
    "```\n",
    "\n",
    "Some types support [_implicit conversions_](#implicit-type-conversion) from\n",
    "other types. For example, an integer value can implicitly convert to a\n",
    "floating-point value:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "99.0\n"
     ]
    }
   ],
   "source": [
    "var temperature: Float64 = 99\n",
    "print(temperature)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example, the `temperature` variable is explicitly typed as `Float64`,\n",
    "but assigned an integer value, so the  value is implicitly converted to a \n",
    "`Float64`. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Implicitly-declared variables\n",
    "\n",
    "You can create a variable with just a name and a value. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "name = String(\"Sam\")\n",
    "user_id = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implicitly-declared variables are strongly typed: they take the type from the\n",
    "first value assigned to them. For example, the `user_id` variable above is type\n",
    "`Int`, while the `name` variable is type `String`. You can't assign a string to\n",
    "`user_id` or an integer to `name`.\n",
    "\n",
    "Implicitly-declared variables are scoped at the function level. You create an\n",
    "implicitly-declared variable the first time you assign a value to a given name\n",
    "inside a function. Any subsequent references to that name inside the function\n",
    "refer to the same variable. For more information, see [Variable\n",
    "scopes](#variable-scopes), which describes how variable scoping differs between\n",
    "explicitly- and implicitly-declared variables."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Explicitly-declared variables\n",
    "\n",
    "You can declare a variable with the `var` keyword. For example:\n",
    "\n",
    "```mojo\n",
    "var name = String(\"Sam\")\n",
    "var user_id: Int\n",
    "```\n",
    "The `name` variable is initialized to the string \"Sam\". The `user_id` variable \n",
    "is uninitialized, but it has a declared type, `Int` for an integer value. All\n",
    "explicitly-declared variables are typed—either explicitly with a \n",
    "[type annotation](#type-annotations) or implicitly when they're initialized with\n",
    "a value.\n",
    "\n",
    "Since variables are strongly typed, you can't assign a variable a\n",
    "value of a different type, unless those types can be \n",
    "[implicitly converted](#implicit-type-conversion). For example, this code will\n",
    "not compile:\n",
    "\n",
    "```mojo\n",
    "var user_id: Int = \"Sam\"\n",
    "```\n",
    "\n",
    "There are several main differences between explicitly-declared variables and\n",
    "implicitly-declared variables:\n",
    "\n",
    "- An explicitly-declared variable can be declared without initializing it:\n",
    "\n",
    "  ```mojo\n",
    "  var value: Float64\n",
    "  ```\n",
    "\n",
    "- Explicitly-declared variables follow [lexical scoping](#variable-scopes),\n",
    "  unlike implicitly-declared variables."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Type annotations"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although Mojo can infer a variable type from from the first value assigned to a \n",
    "variable, it also supports static type annotations on variables. Type \n",
    "annotations provide a more explicit way of specifying the variable's type.\n",
    "\n",
    "To specify the type for a variable, add a colon followed by the type name:\n",
    "\n",
    "```mojo\n",
    "var name: String = get_name()\n",
    "```\n",
    "\n",
    "This makes it clear that `name` is type `String`, without knowing what the \n",
    "`get_name()` function returns. The `get_name()` function may return a `String`,\n",
    "or a value that's implicitly convertible to a `String`.\n",
    "\n",
    ":::note\n",
    "\n",
    "You must declare a variable with `var` to use type annotations.\n",
    "\n",
    ":::\n",
    "\n",
    "If a type has a constructor with just one argument, you can initialize it in\n",
    "two ways:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "var name1: String = \"Sam\"\n",
    "var name2 = String(\"Sam\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Both of these lines invoke the same constructor to create a `String` from a\n",
    "`StringLiteral`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Late initialization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using type annotations allows for late initialization. For example, notice here\n",
    "that the `z` variable is first declared with just a type, and the value is\n",
    "assigned later:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn my_function(x: Int):\n",
    "    var z: Float32\n",
    "    if x != 0:\n",
    "        z = 1.0\n",
    "    else:\n",
    "        z = foo()\n",
    "    print(z)\n",
    "\n",
    "fn foo() -> Float32:\n",
    "    return 3.14"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you try to pass an uninitialized variable to a function or use\n",
    "it on the right-hand side of an assignment statement, compilation fails.\n",
    "\n",
    "```mojo\n",
    "var z: Float32\n",
    "var y = z # Error: use of uninitialized value 'z'\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::note\n",
    "\n",
    "Late initialization works only if the variable is declared with a\n",
    "type.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implicit type conversion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some types include built-in type conversion (type casting) from one type into\n",
    "its own type. For example, if you assign an integer to a variable that has a \n",
    "floating-point type, it converts the value instead of giving a compiler error:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "var number: Float64 = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As shown above, value assignment can be converted into a constructor call if the \n",
    "target type has a constructor that takes a single argument that matches the\n",
    "value being assigned. So, this code uses the `Float64` constructor that takes an\n",
    "integer: `__init__(inout self, value: Int)`.\n",
    "\n",
    "In general, implicit conversions should only be supported where the conversion\n",
    "is lossless.\n",
    "\n",
    "Implicit conversion follows the logic of [overloaded\n",
    "functions](/mojo/manual/functions#overloaded-functions). If the destination\n",
    "type has a single-argument constructor that takes an argument of the source\n",
    "type, it can be invoked for implicit conversion. \n",
    "\n",
    "So assigning an integer to a `Float64` variable is exactly the same as this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "var number = Float64(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly, if you call a function that requires an argument of a certain type \n",
    "(such as `Float64`), you can pass in any value as long as that value type can\n",
    "implicitly convert to the required type (using one of the type's overloaded\n",
    "constructors).\n",
    "\n",
    "For example, you can pass an `Int` to a function that expects a `Float64`,\n",
    "because `Float64` includes a constructor that takes an `Int`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn take_float(value: Float64):\n",
    "    print(value)\n",
    "\n",
    "fn pass_integer():\n",
    "    var value: Int = 1\n",
    "    take_float(value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more details on implicit conversion, see \n",
    "[Constructors and implicit \n",
    "conversion](/mojo/manual/lifecycle/life/#constructors-and-implicit-conversion)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variable scopes\n",
    "\n",
    "Variables declared with `var` are bound by *lexical scoping*. This\n",
    "means that nested code blocks can read and modify variables defined in an\n",
    "outer scope. But an outer scope **cannot** read variables defined in an\n",
    "inner scope at all.\n",
    "\n",
    "For example, the `if` code block shown here creates an inner scope where outer\n",
    "variables are accessible to read/write, but any new variables do not live\n",
    "beyond the scope of the `if` block:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num: 1\n",
      "num: 2\n",
      "num: 1\n",
      "dig: 2\n"
     ]
    }
   ],
   "source": [
    "def lexical_scopes():\n",
    "    var num = 1\n",
    "    var dig = 1\n",
    "    if num == 1:\n",
    "        print(\"num:\", num)  # Reads the outer-scope \"num\"\n",
    "        var num = 2         # Creates new inner-scope \"num\"\n",
    "        print(\"num:\", num)  # Reads the inner-scope \"num\"\n",
    "        dig = 2             # Updates the outer-scope \"dig\"\n",
    "    print(\"num:\", num)      # Reads the outer-scope \"num\"\n",
    "    print(\"dig:\", dig)      # Reads the outer-scope \"dig\"\n",
    "\n",
    "lexical_scopes()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the `var` statement inside the `if` creates a **new** variable with the same name as the outer variable. This prevents the inner loop from accessing the outer `num` variable. (This is called \"variable shadowing,\" where the inner scope variable hides or \"shadows\" a variable from an outer scope.)\n",
    "\n",
    "The lifetime of the inner `num` ends exactly where the `if` code block ends,\n",
    "because that's the scope in which the variable was defined.\n",
    "\n",
    "This is in contrast to implicitly-declared variables (those without the `var`\n",
    "keyword), which use **function-level scoping** (consistent with Python variable\n",
    "behavior). That means, when you change the value of an implicitly-declared\n",
    "variable inside the `if` block, it actually changes the value for the entire\n",
    "function.\n",
    "\n",
    "For example, here's the same code but *without* the `var` declarations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "def function_scopes():\n",
    "    num = 1\n",
    "    if num == 1:\n",
    "        print(num)   # Reads the function-scope \"num\"\n",
    "        num = 2      # Updates the function-scope variable\n",
    "        print(num)   # Reads the function-scope \"num\"\n",
    "    print(num)       # Reads the function-scope \"num\"\n",
    "\n",
    "function_scopes()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, the last `print()` function sees the updated `num` value from the inner\n",
    "scope, because implicitly-declared variables (Python-style variables) use function-level\n",
    "scope (instead of lexical scope)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Mojo",
   "language": "mojo",
   "name": "mojo-jupyter-kernel"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "mojo"
   },
   "file_extension": ".mojo",
   "mimetype": "text/x-mojo",
   "name": "mojo"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
